# -*- coding: utf-8 -*-

#    Copyright (C) 2014-2015 by Promotux
#                       di Francesco Meloni snc - http://www.promotux.it/

#    Author: Francesco Meloni  <francesco@promotux.it>

#    This file is part of OdCollect.

#    OdCollect is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 2 of the License, or
#    (at your option) any later version.

#    OdCollect is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.

#    You should have received a copy of the GNU General Public License
#    along with OdCollect.  If not, see <http://www.gnu.org/licenses/>.

import math
import os
import sys
import random
import re
import feedparser
import ConfigParser
from werkzeug.wrappers import BaseRequest, BaseResponse
from werkzeug import FileStorage
from werkzeug.routing import Map, Rule, NotFound, RequestRedirect
from werkzeug.utils import cached_property
from werkzeug.contrib.securecookie import SecureCookie
import Environment
from web_lib.session import Session
from web_lib.postmarkup import *
from dao.Role import Role
from dao.Action import Action
from dao.User import User
from lib import utils
from PIL import Image, ImageDraw, ImageFont
from random import randint as rint
from Environment import STATIC_PATH , CACHE_DIR , COOKIENAME , SESSION_DIR
try:
    import json
except:
    None
from jinja2 import Environment  as Env
from jinja2 import FileSystemLoader,FileSystemBytecodeCache,environmentfilter, Markup, escape
url_map = Map()

def expose(rule, **kw):
    def decorate(f):
        kw['endpoint'] = f.__name__
        url_map.add(Rule(rule, **kw))
        return f
    return decorate

if not os.path.exists(STATIC_PATH):
    STATIC_PATH= "/home/promo/odmc/tpl"

if not os.path.exists(CACHE_DIR):
    CACHE_DIR= "/home/promo/odmc/cache"

if not os.path.exists(SESSION_DIR):
    SESSION_DIR = "/home/promo/odmc/session"


jinja_env = Env(loader=FileSystemLoader([STATIC_PATH], ),
        bytecode_cache = FileSystemBytecodeCache(os.path.join(CACHE_DIR), '%s.cache'))
#url_map = Map([Rule('/theme/<file>', endpoint='theme', build_only=True)])
#url_map = Map([Rule('/robots.txt', endpoint='/robots.txt', build_only=True)])

#def url_for(endpoint, _external=False, **values):
    #return Environment.local.url_adapter.build(endpoint, values, force_external=_external)

#jinja_env.globals['url_for'] = url_for

def render_template(template, **context):
    templ = template.split("/")
    if templ[0] == "main":
        if hasattr(Environment.main_conf,"Templates") and hasattr(Environment.main_conf.Templates, "main_template_dir"):
            new_tpl_dir = Environment.main_conf.Templates.main_template_dir
            template_ = "/".join(([templ[0]] + [new_tpl_dir] + templ[1:]))
            print "File CON SUB template", template
            try:
                return Response(jinja_env.get_template(template_+".html").render(**context),
                                                            mimetype='text/html')
            except IOError:
                return Response(jinja_env.get_template(template+".html").render(**context),
                    mimetype='text/html')
    try:
        return Response(jinja_env.get_template(template).render(**context),
                    mimetype='text/html')
    except:
        return Response(jinja_env.get_template(template+".html").render(**context),
                    mimetype='text/html')



def datetimeformat(value, format='%d/%m/%Y %H:%M '):
    if not value:
        return ""
    else:
        return value.strftime(format)

jinja_env.filters['datetimeformat'] = datetimeformat

def dateformat(value, format='%d/%m/%Y '):
    if not value:
        return ""
    else:
        return value.strftime(format)

jinja_env.filters['dateformat'] = dateformat

def bbcode(value):
    markup = create(annotate_links=False,target=True, use_pygments=False)
    if not value:
        return ""
    else:
        return markup(value)
jinja_env.filters['bbcode'] = bbcode


def noNone(value):
    if value =="None":
        return ""
    elif not value:
        return ""
    else:
        return value
jinja_env.filters['nonone'] = noNone


@environmentfilter
def url2href(environment, value):
    b = ""
    flag = True
    for a in value:
        if flag and a!="$":
            continue
        else:
            flag = False
            if a !="]":
                b += a
            flag = False
    value = '<a href =%s />%s</a>'  %(b.split(",")[0][5:], b.split(",")[1])
    return value

jinja_env.filters['url2href'] = url2href
_paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')

@environmentfilter
def nl2br(environment, value):
    result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', '<br>\n')
                          for p in _paragraph_re.split(escape(value)))
    if environment.autoescape:
        result = Markup(result)
    return result
jinja_env.filters['nl2br'] = nl2br


class Request(BaseRequest):
    """Create a useful subclass of the base request that
    uses utf-8 internally."""
    charset = 'utf-8'
    def __init__(self, environ, url_adapter=None):
        BaseRequest.__init__(self, environ)
        #self.url_adapter = url_adapter

class Response(BaseResponse):
    """The same for the response object. Also set the default mimetype
    to ``text/html`` since this makes more sense for this example."""
    charset = 'utf-8'
    default_mimetype = 'text/html'

class RedirectResponse(Response):
    """Subclass of `Response` for simple redirecting."""

    def __init__(self, url):
        Response.__init__(self, 'Redirecting to %s...' % url,
                          mimetype='text/plain', status=302)
        self.headers['Location'] = url


class ManagePrint(object):

    def __init__(self, req, docType= None, report = None ):
        self.path = req.environ['PATH_INFO'].split('/')
        self._slaTemplate = Environment.templates_dir + self.path[1] +"/"+ Environment.sladir + docType + '.sla'
        self.pdfFolder = Environment.templates_dir + self.path[1] +"/"+ Environment.sladir
        self.report = report
        print self._slaTemplate

    def pdf(self, param):
        """ Restituisce una stringa contenente il report in formato PDF
        """
        self._slaTemplateObj = Sla2Pdf(slaFileName=self._slaTemplate,
                                           pdfFolder=self.pdfFolder,
                                           report=self.report)

        param = param
        return self._slaTemplateObj.serialize(param)


def renderizza(req,tpl,pageData):
    pageData["USER"] = getUserFromId(req)
    env = Env(loader=FileSystemLoader(Environment.CONFIGPATH +"/templates_email"))
    def noNone(value):
        if value =="None":
            return ""
        elif not value:
            return ""
        else:
            return value
    env.filters['nonone'] = noNone

    def dateformat(value, format='%d/%m/%Y '):
        if not value:
            return ""
        else:
            return value.strftime(format)

    env.filters['dateformat'] = dateformat
    tpl2 = env.get_template(tpl)
    html = tpl2.render(pageData=pageData)
    return html

def renderTemplate(pageData):
    #jinja_env.globals['environment'] = Environment
    jinja_env.globals['utils'] = utils
    pageData["titolo"] = pageData["file"].split(".")[0].capitalize()
    if "dao" in pageData:
        html = jinja_env.get_template("/"+pageData["file"]+".html").render(pageData = pageData, dao=pageData["dao"])
    else:
        html = jinja_env.get_template("/"+pageData["file"]+".html").render(pageData = pageData)
    return html


def addSlash(url=None):
    if url:
        return "/"+url
    else:
        return ""



def createRandomString(num=10):
    b = ""
    for c in range(num):
        a = random.choice('1234567890abcdefghilmnopqrstuvz')
        b = b + a
    return b


def hasActionWeb(req=None, action=[], red="/"):
    """
    Importante il controllo se il ruolo è attivo
    se l'utente ha una sessione aperta ed ha i privilegi adeguati
    admin =  1,2,3,4,5
    utente = 1,2
    cliente = 1,2
    guest = 0
    il cliente web adesso ha il suo id che è 16 WEB-LOGIN
    l'admin invece ha sempre tutto pure il 17 che è WEB-ADMIN
    """
    from dao.RoleAction import RoleAction
    if Session(req).control():
        id_role = getIdRoleFromIdUser(req)
        ruol = Role().getRecord(id=id_role)
        if not ruol.active:
            return False
    else:
        test = Role().select(name="Guest")
        if test:
            id_role = test[0].id
        return False
    for act in action:
        can = RoleAction().select(id_role=id_role,
                                id_action=act,
                                batchSize=None)
        if not can:
            return False
    return True

jinja_env.globals['hasActionWeb'] = hasActionWeb

def leggiInSessione(req=None, sezione="Main", chiave=None, app=False, sch=None):
    """Funzione più generale che restituisce il valore di un campo in un determinato
    blocco del file di sessione """
    if not req:
        req = Environment.req
    if Environment.census and Environment.sch:
        return Environment.sch
    config = ConfigParser.RawConfigParser()
    valore = None
    if req:
        try:
            sid = req.cookies[COOKIENAME]
            session_file = SESSION_DIR + "/" + sid
            config.read(session_file)
            if config.has_option(sezione, chiave):
                valore = config.get(sezione, chiave)
            if valore =="None":
                return None
        except:
            pass
    return valore



def getRoleFromId(req):
    """
        ok ported to new pg2 Dao
    """
    idr = Session(req).getUserId()
    user = User(req=req).getRecord(id=idr)
    if user:
        id_role = user.id_role
        role = Role(req=req).getRecord(id=id_role)
        if not role.id:
                roleName = "Guest"
        else:
            roleName= role.name
    else:
        idopr = Session(req).getOperId()
        if idopr and leggiInSessione(req, sezione="Main", chiave="schema"):
            from dao.Operatore import Operatore
            ope = Operatore().getRecord(id=idopr)
            roleName = ope.tipo_operatore
        else:
            roleName = "Guest"
    return roleName

def getIdRoleFromIdUser(req):
    ids = Session(req).getUserId()
    if ids == 0:
        role = Role(req=req).select(name ="Guest")
        roleId = role[0].id
    else:
        role = User(req=req).getRecord(id=ids)
        roleId = role.id_role
    return roleId


def getUserFromId(req):
    """
        ok, adattata ai nuovi Dao pG2
    """
    idrr = Session(req).getUserId()
    if not idrr:
        return None
    user = User(req=req).getRecord(id=idrr)
    if not user :
        return None
    else:
        return user

def getUsernameFromId(req):
    """
        ok, adattata ai nuovi Dao pG2
    """
    idrr = Session(req).getUserId()
    if not idrr:
        idopr = Session(req).getOperId()
        if idopr and leggiInSessione(req, sezione="Main", chiave="schema"):
            from dao.Operatore import Operatore
            ope = Operatore().getRecord(id=idopr)
            return ope.username
        else:
            return "Guest"
    user = User(req=req).getRecord(id=idrr)
    if not user :
        return "Guest"
    else:
        return user.username

def includeFile(files, subdomain=None):
    """
        This search for the right template file in common or theme dir
    """
    print "FILE DEL TEMPLATE", files
    filename= files+'.html'
    pathFile = 'tpl/'
    if os.path.exists(str(pathFile+filename)):
        pathFile = filename
        return pathFile
    elif os.path.exists(str(templates_dir[0] + "/" + filename)):
        pathFile = filename
        return pathFile
    else:
        pathFile = None
    return pathFile


def resizeImgThumbnailGeneric(req=None, name=None):
    """
    funzione di ridimensionamento immagine per la lista, di fatto
    crea un thumnail dell'immagine stessa
    """
    path=req.environ['PATH_INFO'].split('/')
    nameuser = getUsernameFromId(req)
    envtDir = Environment.configPath+"style/" +path[1]+"/data/"+nameuser+"/images"
    imageFile = envDir +"/"+name
    im1 = Image.open(imageFile)
    width = int(Environment.params[path[1]]['widthThumbnail'])
    height = int(Environment.params[path[1]]['heightThumbnail'])
    im5 = im1.resize((width, height), Image.ANTIALIAS)
    newname= 'thumb_'+ name
    im5.save(envDir +"/"+ newname)


def prepareUserEnv(req):
    nameuser = getUsernameFromId(req)
    envDir = Environment.CONFIGPATH+"/templates/media/" +nameuser+"/"+"images"
    if not (os.path.exists(envDir)):
        os.makedirs(envDir)
    return envDir

def checkPath(path=None, correctPath=None):
    for a in correctPath:
        if a not in path:
            return False
    return True


def getfeedFromSite(name=None, items=3):
    string = ""
    #if Environment.feedAll == "":
    feedToHtml = []
    try:
        feed=Feed().select(name=name)[0]
        feedurl = feed.url
        d = feedparser.parse(feedurl)
        feedList = d['entries']
        for feed in feedList[:items]:
            try:
                body = feed['content'][0]['value']
            except:
                body = feed["summary_detail"]['value']
            feed = {
                "title" :feed['title'],
                "links": feed['links'][0]['href'],
                "body" : body,
                "updated" : feed['updated'][4:-14],
                "autore" : feed['author']
                }
            feedToHtml.append(feed)
        #Environment.feedCache = feedToHtml
        #self.renderPage(feedToHtml)
        return feedToHtml
    except:
        feed = {
                "title" : "",
                "links":  "",
                "body" :  "",
                "updated" :  "",
                "autore" :  ""
                }
        feedToHtml.append(feed)
        return feedToHtml

def permalinkaTitle(string):
    import unicodedata
    string = unicodedata.normalize("NFKD",string).encode('ascii','ignore').strip().lower()
    test = "-".join(string.split())
    badchar = []
    for char in test:
        if char not in "qwertyuiopasdfghjklzxcvbnm1234567890-_":
            badchar.append(char)
    if badchar:
        for ch in badchar:
            test = test.replace(str(ch),"")
    return test

def pagination(req,batch,count):
    """ Funzione che gestisce la paginazione delle liste semplici come news e faq """
    pag  = req.args.get('pag')
    pages = req.args.get('pages')
    searchkey= req.form.get('searchkey')
    args = req.args.to_dict()
    if not searchkey:
        searchkey= req.args.get('searchkey')
    if not pag:
        pag = 1
    else:
        pag = int(pag)
    if pag < 2:
        offset = 0
    else:
        offset = (int(pag)*batch)-batch
    if not pages or searchkey :
        if count:
            pages = int(math.ceil(float(count)/float(batch)))
        else: pages = 1
    args["pages"] = pages
    args["pag"] = pag
    args["searchkey"] = searchkey
    args["count"] = count
    args["offset"] = offset
    return args


def createcaptcha():
    img = Image.new("RGB", (220, 75), "#FFFFFF")
    draw = ImageDraw.Draw(img)
    pathFile1 = os.path.split(os.path.dirname(__file__))[0]+"/tpl/main"
    pathFile = Environment.CACHE_DIR
    font = ImageFont.truetype(pathFile1+"/Trash_.ttf", 52)
    r,g,b = rint(0,255), rint(0,255), rint(0,255)
    dr = (rint(0,255) - r)/300.
    dg = (rint(0,255) - g)/300.
    db = (rint(0,255) - b)/300.
    for i in range(300):
        r,g,b = r+dr, g+dg, b+db
        draw.line((i,0,i,300), fill=(int(r),int(g),int(b)))
    string = ""
    values = "23456789QWERTYUPASDFGHJKLZXCVBNMabcdefghmnpqrstuvz"
    for a in range(5):
        b =  rint(0,35)
        string += values[b]
    draw.text((20, 20), string, font=font)
    img.save(pathFile1+"/captcha.png", "PNG")
    return string


def hasModule(name=""):
    if hasattr(Environment.main_conf, "Modulo"):
        moduli = [x for x in Environment.main_conf.Modulo.items()]
        print "MODULI ATTIVI", moduli
        if (name.lower(),"True") in moduli or (name.lower(), "yes") in moduli:
            Environment.modulesList.append(name)
            return True
        else:
            return False
jinja_env.globals['hasModule'] = hasModule

def orda(name):
     a = "".join([str(ord(x)) for x in list(name)])
     return a



def salvaInSessione(req, sezione="Main", chiave=None, valore=None, app=False):
    """ Funzione che salva l'attività nel file di sessione
    o aggiorna l'esistente"""
    if app:
        return True
    config = ConfigParser.RawConfigParser()
    if req:
        try:
            sid = req.cookies[COOKIENAME]
            session_file = SESSION_DIR + "/" + sid
            config.read(session_file)
            config.set(sezione, chiave, valore)
            with open(session_file, 'wb') as configfile:
                config.write(configfile)
            return True
        except:
            pass
    return False

def change_schema(req,sch, app=False):
    """ Funziona importantissima perchè permette di cambiare schema ente,
    di scaricare i dao già caricati e poi ricarne di nuovi"""
    schema = leggiInSessione(req, sezione="Main", chiave="schema", app=app, sch=sch)
    if (sch == schema) and not app:
        return Response("OK")
    else:
        Environment.meta.clear()
        Environment.meta.reflect(schema="main")
        if sch =="" and not app:
            salvaInSessione(req, sezione="Main", chiave="schema", valore=None)
        else:
            salvaInSessione(req, sezione="Main", chiave="schema", valore=sch)
            Environment.fk_prefix = sch+"."
            #Environment.session.execute("SET search_path TO {0}".format(sch))
    print "SCHEMA CAMBIATO IN CHANGE SCHEMA", sch
    for a in ["dao.Campo", "dao.TipoCategoria","dao.Categoria", "dao.Setconf", "dao.CategoriaCampo", "dao.EnteCategoria", "dao.OpenData", "dao.News", "dao.StaticPages","dao.Faq","dao.Operatore", "dao.CategoriaTag", "dao.ParametriExport", "dao.Segnalazione", "dao.TipoSegnalazione", "dao.StatoSegnalazione", "dao.PrioritaSegnalazione", "dao.Esportazione","dao.PercorsoSegnalazione", "dao.Organization"]:
        if a in sys.modules:
            del(sys.modules[a])


def generateRandomBarCode(ean=13):
    """
    funzione di generazione codice ean13 random
    utile per quei prodotti che non hanno un codice
    chiaramente solo per uso interno
    """
    import random
    from promogest.dao.CodiceABarreArticolo import CodiceABarreArticolo
    codice = ''

    def create(ean):
        """
        crea un codice di tipo ean
        @param ean: tipo di codice ( al momento gestisce  ean8 ed ean13)
        @type ean: int ( 8 o 13 )
        """
        code = [8, 0]
        if ean == 13:
            for a in xrange(10):
                code.append(random.sample(
                                    [1, 2, 3, 4, 5, 6, 7, 8, 9, 0], 1)[0])
            dispari = (code[1] \
                        + code[3] \
                        + code[5] \
                        + code[7] \
                        + code[9] \
                        + code[11]) * 3
            pari = code[0] + code[2] + code[4] + code[6] + code[8] + code[10]
        elif ean == 8:
            for a in xrange(5):
                code.append(random.sample(
                                    [1, 2, 3, 4, 5, 6, 7, 8, 9, 0], 1)[0])
            dispari = (code[0] + code[2] + code[4] + code[6]) * 3
            pari = code[1] + code[3] + code[5]
        tot = 10 - ((dispari + pari) % 10)
        if tot == 10:
            tot = 0
        code.append(tot)
        b = ''
        for d in code:
            b = b + str(d)
        return b
    correct = False
    while correct is False:
        codice = create(ean)
        there = CodiceABarreArticolo().select(codice=codice)
        if not there:
            return codice
        else:
            create(ean)
